home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Applications… / Banana Jr. ƒ / printing.c < prev   
Encoding:
C/C++ Source or Header  |  1996-03-20  |  11.7 KB  |  460 lines  |  [TEXT/KAHL]

  1. /*
  2.     Printing.c
  3.     
  4.     This file contains the printing routines for "all shapes".
  5.  
  6.     Created        9/2/92        - Dave Hersey
  7.  
  8.     ----------------------------------------------
  9.  
  10.     2/93    debugged and plopped on GX CD.  - dmh
  11.     9/93    updated to run with the ß2 "GXified" interface files. - PLA
  12.     12/93    updated for b3.  - dmh
  13.     3/94    updated for b4.  - dmh
  14.     3/94    general cleanup/debugging. - dmh
  15.     5/94    …and some more. - dmh
  16.     8/94    universalized. - dmh
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <FontLibrary.h>
  21. #include <GXExceptions.h>
  22. #include <GraphicsLibraries.h>
  23. #include <GXEnvironment.h>
  24. #include <GXErrors.h>
  25. #include <QDLibrary.h>
  26. #include <GXPrinting.h>
  27. #include <Collections.h>
  28.  
  29. #include "Banana Jr.h"
  30.  
  31.  
  32. /*------ SetUpEditMenuRec ------------------------------------------------------------------------------------*/
  33. //
  34. //    This routine sets up an gxEditMenuRecord which references our edit menu.  This structure
  35. //    is used by the GXJobDefaultFormatDialog and GXJobPrintDialog calls to allow cut, copy,
  36. //    & paste operations from the dialogs.
  37. //
  38. void SetUpEditMenuRec(gxEditMenuRecord *edMenuRec)
  39. {
  40.  
  41.     edMenuRec->editMenuID = mEdit;
  42.     edMenuRec->cutItem = iCut;
  43.     edMenuRec->copyItem = iCopy;
  44.     edMenuRec->pasteItem = iPaste;
  45.     edMenuRec->clearItem = iClear;
  46.     edMenuRec->undoItem = iUndo;
  47. }
  48.  
  49.  
  50. /*------ DoDocFormat ---------------------------------------------------------------------------------*/
  51. //
  52. //    This routine performs GX's equivalent of the Page Setup (PrStlDialog) call of
  53. //    the old printing architecture.
  54. //
  55. OSErr DoDocFormat(WindowPtr wind, gxDialogResult    *result)
  56. {
  57.     OSErr            err;
  58.     gxEditMenuRecord    edMenuRec;
  59.     gxJob                docJob;
  60.     TH_Doc            doc;
  61.  
  62. //    If we have a non-nil WindowPtr, set up our edit menu record and handle the job
  63. //    format dialog.  Remember to check for errors.
  64.  
  65.     if (wind)
  66.     {
  67.         doc = GetDoc(wind);
  68.         docJob = GetDocJob(doc);
  69.         SetUpEditMenuRec(&edMenuRec);
  70.  
  71.         *result = GXJobDefaultFormatDialog(docJob, &edMenuRec);
  72.         err = GXGetJobError(docJob);
  73.     }
  74.     
  75.     return err;
  76. }
  77.  
  78.  
  79. /*------ DoPageFormat ------------------------------------------------------------------------------*/
  80. //
  81. //    This routine performs a by-page format.  In other words, it sets formatting info
  82. //    for only the current page.
  83. //
  84. OSErr DoPageFormat(WindowPtr wind, gxDialogResult *result)
  85. {
  86.     OSErr                err = noErr;
  87.     gxEditMenuRecord    edMenuRec;
  88.     gxJob                docJob;
  89.     TH_Doc                doc;
  90.     TH_Page                docPage;
  91.     gxFormat            pageFormat;
  92.  
  93. //    If we have a non-nil WindowPtr, set up our edit menu record and handle the job
  94. //    format dialog.  Remember to check for errors.
  95.  
  96.     if (wind)
  97.     {
  98.         SetUpEditMenuRec(&edMenuRec);
  99.         doc = GetDoc(wind);
  100.         docJob = GetDocJob(doc);
  101.         docPage = GetDocPage(doc, (*doc)->curPage);
  102.         pageFormat = (*docPage)->pageFormat;
  103.  
  104.         *result = GXFormatDialog(pageFormat, &edMenuRec, nil);
  105.         
  106.         if (*result == gxRevertSelected)
  107.         {
  108.             GXDisposeFormat(pageFormat);
  109.             (*docPage)->pageFormat = GXNewFormat(docJob);
  110.         }
  111.         
  112.         err = GXGetJobError(docJob);
  113.     }
  114.     
  115.     return err;
  116. }
  117.  
  118.  
  119. /*------ DoPrinting ----------------------------------------------------------------------------------*/
  120. //
  121. //    This routine performs GX's equivalent of the PrJobDialog call in the old
  122. // printing architecture, and then prints the document if the user wants to.
  123. //
  124. OSErr DoPrinting(WindowPtr wind)
  125. {
  126.     OSErr                err = noErr;
  127.     gxDialogResult        result;
  128.     gxEditMenuRecord    edMenuRec;
  129.     gxJob                docJob;
  130.     TH_Doc                doc;
  131.     gxFormat            jobFormat;
  132.     gxMapping            formatMapping;
  133.     gxViewPort            formatVPort;
  134.  
  135. //    If we have a non-nil WindowPtr, set up our edit menu record and handle the print
  136. //    job dialog.  Remember to check for errors.  If no errors occur, and the user clicks
  137. //  ok, print the window's document.
  138.  
  139.     if (wind)
  140.     {
  141.         doc = GetDoc(wind);
  142.         docJob = GetDocJob(doc);
  143.         
  144.         SetUpEditMenuRec(&edMenuRec);
  145.         result = GXJobPrintDialog(docJob, &edMenuRec);
  146.         err = GXGetJobError(docJob);
  147.                 
  148.         if ((result == gxOKSelected) && !(err))
  149.             err = DoPrintLoop(wind);
  150.     }
  151.     
  152.     return err;
  153. }
  154.  
  155.  
  156. /*******************************************************************
  157.     MyPrintOneCopy sets up our job collection items for printing
  158.     one copy of a document, and then prints the document.
  159.     
  160. ********************************************************************/
  161.  
  162. OSErr MyPrintOneCopy(WindowPtr wind)
  163. {
  164.     OSErr                    err;
  165.     Collection                jobCollection;
  166.     gxCopiesInfo            copiesInfo;
  167.     gxFileDestinationInfo    destInfo;
  168.     gxPageRangeInfo            pageRangeInfo;
  169.     Ptr                        oldCopiesInfo = nil, oldPageRangeInfo = nil, oldDestInfo = nil;
  170.     long                    oldCopiesSize, oldPageRangeInfoSize, oldDestInfoSize;
  171.     TH_Doc                    doc = GetDoc(wind);
  172.  
  173.  
  174. /* Get the job collection and set it up to print one copy…    */
  175.  
  176.     jobCollection = GXGetJobCollection(GetDocJob(doc));
  177.  
  178.  
  179. /* Set number of copies to 1.            */
  180.     
  181.     copiesInfo.copies = 1;
  182.     err = MyReplaceCollectionItem(&copiesInfo, sizeof(gxCopiesInfo),
  183.                                     gxCopiesTag, gxPrintingTagID,
  184.                                     jobCollection, &oldCopiesInfo, &oldCopiesSize);
  185.     nrequire(err, ReplaceCopies_error);
  186.  
  187.  
  188. /* Set page range to "all".    */
  189.     
  190.     pageRangeInfo.simpleRange.optionChosen = gxDefaultPageRange;
  191.     pageRangeInfo.minFromPage = 1;
  192.     pageRangeInfo.simpleRange.fromPage = 1;
  193.     pageRangeInfo.maxToPage = (*doc)->numPages;
  194.     pageRangeInfo.simpleRange.toPage = (*doc)->numPages;
  195.     pageRangeInfo.simpleRange.printAll = true;
  196.     err = MyReplaceCollectionItem(&pageRangeInfo, sizeof(gxPageRangeInfo),
  197.                                     gxPageRangeTag, gxPrintingTagID,
  198.                                     jobCollection, &oldPageRangeInfo, &oldPageRangeInfoSize);
  199.     nrequire(err, ReplacePageRange_error);
  200.  
  201.  
  202. /* Set destination to "printer".        */
  203.  
  204.     destInfo.toFile = false;
  205.     err = MyReplaceCollectionItem(&destInfo, sizeof(gxFileDestinationInfo),
  206.                                   gxFileDestinationTag, gxPrintingTagID,
  207.                                   jobCollection, &oldDestInfo, &oldDestInfoSize);
  208.     nrequire(err, ReplaceDestination_error);
  209.  
  210.  
  211. /* Print one copy of our document.        */
  212.  
  213.     err = DoPrintLoop(wind);
  214.  
  215.  
  216. /*    Restore original number of copies, page range, and output
  217.     destination in case anybody uses that info. */
  218.  
  219. ReplaceCopies_error:
  220.     MyReplaceCollectionItem(oldCopiesInfo, oldCopiesSize,
  221.                               gxCopiesTag, gxPrintingTagID,
  222.                             jobCollection, nil, nil);
  223.  
  224. ReplacePageRange_error:
  225.     MyReplaceCollectionItem(oldPageRangeInfo, oldPageRangeInfoSize,
  226.                             gxPageRangeTag, gxPrintingTagID,
  227.                             jobCollection, nil, nil);
  228.  
  229. ReplaceDestination_error:
  230.     MyReplaceCollectionItem(oldDestInfo, oldDestInfoSize,
  231.                             gxFileDestinationTag, gxPrintingTagID,
  232.                             jobCollection, nil, nil);
  233.  
  234.  
  235. /* Dispose of the pointers that MyReplaceCollectionItem created. */
  236.  
  237.     if (oldCopiesInfo)
  238.         DisposePtr(oldCopiesInfo);
  239.  
  240.     if (oldPageRangeInfo)
  241.         DisposePtr(oldPageRangeInfo);
  242.  
  243.     if (oldDestInfo)
  244.         DisposePtr(oldDestInfo);
  245.  
  246.     return err;
  247. }
  248.  
  249.  
  250.  
  251. /*******************************************************************
  252.     MyReplaceCollectionItem is a generic routine that replaces a
  253.     collection item with the passed data.  If the oldData parameter
  254.     is not nil, this routine creates a pointer and returns the data
  255.     that's being replaced in it.  (If the item doesn't already exist,
  256.     then a copy of the newData is returned instead.)
  257.     
  258. ********************************************************************/
  259.  
  260. OSErr MyReplaceCollectionItem(void *newData, long collectSize,
  261.                               OSType collectType, long collectID,
  262.                               Collection whichCollection,
  263.                               Ptr *oldData, long *oldDataSize)
  264. {
  265.     OSErr    err = noErr;
  266.     long    index;
  267.  
  268. /*
  269.     If we're supposed to return the old data, get it.
  270.     If there is no old data, return a copy of the new data.
  271. */
  272.  
  273.     if (oldData)
  274.     {
  275.         err = GetCollectionItemInfo(whichCollection,
  276.                                     collectType,
  277.                                     collectID,
  278.                                     dontWantIndex,
  279.                                     oldDataSize,
  280.                                     dontWantAttributes);
  281.  
  282.         if (err)
  283.         {
  284.             *oldDataSize = collectSize;
  285.             *oldData = NewPtrSys(*oldDataSize);
  286.             if (!(err = MemError()))
  287.                 BlockMove(newData, *oldData, collectSize);
  288.         }
  289.         else
  290.         {
  291.             *oldData = NewPtrSys(*oldDataSize);
  292.             if (!(err = MemError()))
  293.                 err = GetCollectionItem(whichCollection,
  294.                                         collectType,
  295.                                         collectID,
  296.                                         dontWantSize,
  297.                                         *oldData);
  298.         }
  299.     }
  300.  
  301.     nrequire(err, CouldNotSetOldData);
  302.  
  303.  
  304. // If we're adding a new collection item, do so.  Otherwise, get the
  305. // existing item's index and replace the old collection item.
  306.  
  307.     err = AddCollectionItem(whichCollection,
  308.                             collectType,
  309.                             collectID,
  310.                             collectSize,
  311.                             newData);
  312.  
  313.     if (err == collectionItemLockedErr)
  314.     {
  315.         err = GetCollectionItemInfo(whichCollection,
  316.                                     collectType,
  317.                                     collectID,
  318.                                     &index,
  319.                                     dontWantSize,
  320.                                     dontWantAttributes);
  321.         if (!err)
  322.             err = ReplaceIndexedCollectionItem(whichCollection,
  323.                                                index,
  324.                                                collectSize,
  325.                                                newData);
  326.     }
  327.  
  328. CouldNotSetOldData:
  329.     return err;
  330. }
  331.  
  332.  
  333.  
  334. /*------ DoPrintLoop ----------------------------------------------------------------------------------*/
  335. //
  336. //    This routine prints the window's document using whatever job and format
  337. //    is currently attached to it.  (If the window wwere just created and then the user
  338. //    selected Print One Copy w/o first selecting Page Setup…, the system default job and
  339. //    format are stored with this document.
  340. //
  341. OSErr DoPrintLoop(WindowPtr wind)
  342. {
  343.     OSErr        err = noErr;
  344.     gxJob        docJob;
  345.     Str255        title;
  346.     TH_Doc        doc;
  347.     TH_Page        docPage;
  348.     gxFormat    pageFormat;
  349.     gxShape     pageShape, coverPage;
  350.     long        firstPg, lastPg, pg, numPages;
  351.  
  352. //    If we have a non-nil WindowPtr, start the print job, print a page and then finish
  353. //    the job.  Remember to check those errors!
  354.  
  355.     if (wind)
  356.     {
  357.         doc = GetDoc(wind);
  358.         docJob = GetDocJob(doc);
  359.         numPages = (*doc)->numPages;
  360.         GetWTitle(wind, title);
  361.         
  362.         GXGetJobPageRange(docJob, &firstPg, &lastPg);
  363.  
  364.         firstPg = (firstPg < 1)? 1: (firstPg > numPages)? numPages: firstPg;
  365.         lastPg = (lastPg < firstPg)? firstPg: (lastPg > numPages)? numPages: lastPg;
  366.         numPages = lastPg - firstPg +1;
  367.         
  368.         GXStartJob(docJob, title, numPages);
  369.         err = GXGetJobError(docJob);
  370.         
  371.         for (pg = firstPg; (!err) && (pg <= lastPg); pg++)
  372.         {
  373.             docPage = GetDocPage(doc, pg);
  374.             pageFormat = (*docPage)->pageFormat;
  375.             pageShape = GXCopyToShape(nil, GetDocShape(doc, pg));
  376.             CheckForIdiots(pageFormat, pageShape);
  377.  
  378.             GXPrintPage(docJob, pg, pageFormat, pageShape);
  379.             
  380.             GXDisposeShape(pageShape);
  381.             err = GXGetJobError(docJob);
  382.         }
  383.  
  384.         GXFinishJob(docJob);
  385.         if (!err) err = GXGetJobError(docJob);
  386.     }
  387.     return err;
  388. }
  389.  
  390.  
  391. void CheckForIdiots(gxFormat aFormat, gxShape pageShape)
  392. {
  393.     OSErr                    err;
  394.     Collection                fmtCollection;
  395.     T_BananaCollection        bananaConfig;
  396.     gxShape                     theText;
  397.     Str255                    textStr;
  398.     long                    numChars;
  399.     
  400.     fmtCollection = GXGetFormatCollection(aFormat);
  401.  
  402.     err = GetCollectionItem(fmtCollection, kBananaCollectionType,
  403.                               gxPrintingTagID, nil, &bananaConfig);
  404.     
  405.     if (!err)
  406.     {
  407.         if (bananaConfig.one || bananaConfig.two ||
  408.             bananaConfig.three || bananaConfig.four)
  409.         {
  410.             theText = GXNewShape(gxTextType);
  411.             GXSetShapeTextSize(theText, ff(32));
  412.             SetShapeCommonFont(theText, timesFont);
  413.             GXMoveShapeTo(theText, ff(10), ff(40));
  414.  
  415.             if (bananaConfig.two)    // Idiots setting
  416.             {
  417.                 numChars = sprintf((Ptr) &textStr[0], "%s", "Idiots enabled.");
  418.                 GXSetText(theText, numChars, textStr, nil);
  419.  
  420.                 AddToShape(pageShape, theText);
  421.                 GXMoveShape(theText, ff(0), ff(40));
  422.             }
  423.  
  424.             if (bananaConfig.three)    // Random Printing setting
  425.             {
  426.                 numChars = sprintf((Ptr) &textStr[0], "%s", "Random Printing Enabled.");
  427.                 GXSetText(theText, numChars, textStr, nil);
  428.  
  429.                 AddToShape(pageShape, theText);
  430.                 GXMoveShape(theText, ff(0), ff(40));
  431.             }
  432.  
  433.             if (bananaConfig.four)    // Page Shuffling setting
  434.             {
  435.                 numChars = sprintf((Ptr) &textStr[0], "%s", "Page Shuffling enabled.");
  436.                 GXSetText(theText, numChars, textStr, nil);
  437.  
  438.                 AddToShape(pageShape, theText);
  439.                 GXMoveShape(theText, ff(0), ff(40));
  440.             }
  441.  
  442.             if (bananaConfig.one)    // 360° Rotation setting
  443.             {
  444.                 numChars = sprintf((Ptr) &textStr[0], "%s", "360° Rotation enabled.");
  445.                 GXSetText(theText, numChars, textStr, nil);
  446.  
  447.                 AddToShape(pageShape, theText);
  448.             }
  449.  
  450.             GXDisposeShape(theText);
  451.         }
  452.     }
  453. }
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.